home *** CD-ROM | disk | FTP | other *** search
- ; XDEF compress_slow
-
- ;On entry:
- ; a0 = InBuf
- ; a1 = OutBuf
- ; a2 = HashTab
- ; d0 = InLen
-
- compress_slow:
- movem.l a3-a6/d1-d7,-(sp)
- move.l a0,d1 ; d1=src+src_len+2
- add.l d0,d1 ; since all srcpointers are
- addq.l #2,d1 ; 2 to big we need this +2 !
-
- moveq.l #$FFFFFFFC,d2
- and.l d0,d2
- add.l a1,d2
- move.l d2,a4 ; a4=dst+(src_len & ~3)
-
- movem.l a1/a4,-(sp) ; save dst and dst_end for later use
-
- ;;; lea $40000(a2),a6 ; a6=hh a6-$40000 == hash
- moveq.l #4,d0
- swap d0
- move.l a2,a6
- add.l d0,a6
-
- lea.l -4096(a0),a5
- move.w #$10FF,d2
- hfill: move.l a5,(a2)+ ; fill hash with src-4096
- move.l a5,(a2)+ ; hash is $1100*$10 = $11000 longs big
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- move.l a5,(a2)+
- dbra d2,hfill
-
- moveq.l #-1,d0 ; d0 = 4*hash_fkt(s,s+1,s+2)
- move.b (a0)+,d0 ; a0 += 2
- lsl.w #8,d0
- move.b (a0)+,d0
- add.b (a0),d0
- lsl.l #2,d0
-
- move.l a0,0(a6,d0.l) ; hash[hash_val]=s
-
- move.l #$00000FFF,d4
-
- subq.l #2,a4
- move.l a4,a3 ; get place to put next ctrl_word
- moveq.l #1,d7 ; initialize ctrl_word with $0001
-
- move.l a0,d2
- sub.l d4,d2 ; d2 = src - 4095
-
- ; bra.s do_literal2 ; The first one is always a literal.
-
- ;REGISTER MAP
- ;============
-
- ; a0 source
- ; a1 destination byte stream (post increment)
- ; a2 Temporary
- ; a3 place to put control word in output
- ; a4 destination word stream (pre decrement)
- ; a5 Temporary
- ; a6 hashtable
- ; a7 Stack pointer. Don't touch!
-
- ; d0 Temporary
- ; d1 End of input+2
- ; d2 src - 4095
- ; d3 match_offset , match_len
- ; d4 Constant 4095
- ; d5 work pointer into LZ77-window
- ; d6 Temporary
- ; d7 Buffers the current control word.
-
- ;;;---------------------------------------------------------------------------
-
- do_literal2:
- move.b -2(a0),(a1)+ ; write literal
-
- moveq.l #-1,d0 ; increment src
- move.b -1(a0),d0
- lsl.w #8,d0
- move.b (a0)+,d0 ; ++a0
- addq.l #1,d2 ; d2+=1 d2==src-4095
- add.b (a0),d0
- lsl.l #2,d0 ; d0 = hash_fkt(src[-2],src[-1],src[0])
-
- move.l 0(a6,d0.l),d5 ; d5 = wrk = hash[hash_val]
- move.l a0,0(a6,d0.l) ; hash[hash_val] = src
-
- move.w a0,d0
- and.w d4,d0
- asl.w #2,d0 ; clears X
- move.l d5,0(a6,d0.w) ; hh[src&$FFF] = [old]hash[hash_val] {== wrk}
-
- insctl: addx.w d7,d7 ; inject X-Flag into ctrl_word
- bcc.s eloop ; control not full
-
- move.w d7,(a3) ; write ctrl_word to it's place
- subq.l #2,a4
- move.l a4,a3 ; get place to put next ctrl_word
-
- moveq.l #1,d7 ; initialize ctrl_word with $0001
- cmp.l d1,a0 ; Has src reached src_end?
- bcc end_control_done
-
- eloop: cmp.l d2,d5 ; is wrk below the limit
- bmi.s do_literal2 ; is wrk < src - 4095
- moveq.l #1,d3 ; Initializations for iloop
- ; match_ofs,match_len-1 = 0,1
-
- iloop: move.l a0,a2
- move.l d5,a5
-
- MATCH MACRO
- cmp.b (a2)+,(a5)+
- bne.s \1
- ENDM
-
- MATCH next ; 2
- MATCH mism ; 3
- MATCH mism ; 4
- MATCH mism ; 5
- MATCH mism ; 6
- MATCH mism ; 7
- MATCH mism ; 8
- MATCH mism ; 9
- MATCH mism ;10
- MATCH mism ;11
- MATCH mism ;12
- MATCH mism ;13
- MATCH mism ;14
- MATCH mism ;15
- MATCH mism ;16
- MATCH mism ;17
- addq.l #1,a5 ;18
- mism: sub.l d5,a5 ; a5=match_len-1
-
- cmp.w a5,d3
- bcc.s next ; new match is not longer than old one
-
- move.w a0,d3
- sub.w d5,d3 ; d3 = src - wrk = match_ofs
- swap d3
- move.w a5,d3 ; match_ofs,match_len-1 is updated.
-
- cmp.b #17,d3
- bcc.s docopy ; match_len-1 >= 18-1
-
- next: and.w d4,d5 ; d5=wrk & $00000FFF
- lsl.w #2,d5
- move.l 0(a6,d5.w),d5 ; wrk=hh[wrk & $00000FFF]
-
- cmp.l d2,d5 ; is wrk in range?
- bcc.s iloop ; is wrk >= src - 4095 ?
-
-
- finished_chain:
- cmp.b #2,d3
- bcs do_literal2
-
- docopy: moveq.l #17,d0
- add.l d0,d2
- sub.b d3,d0 ; d0=17-(match_len-1)
- sub.l d0,d2
- addq.l #1,d2 ; d2+=match_len
-
- swap d3
- asl.w #4,d3
- or.b d0,d3 ; d3 = OOOOOOOO OOOOLLLL
-
- move.w d3,-(a4) ; write copyinfo
-
- swap d3 ; d3.w = match_len - 1
-
- incsrc: moveq.l #-1,d0 ; increment src
- move.b -1(a0),d0
- lsl.w #8,d0
- move.b (a0)+,d0
- add.b (a0),d0 ; ++a0
-
- move.w a0,d6
- and.w d4,d6
- asl.w #2,d6
-
- asl.l #2,d0 ; d0 = hash_fkt(src[-2],src[-1],src[0])
- ; Does set the X-Flag
- move.l 0(a6,d0.l),d5 ; d5 = wrk = hash[hash_val]
- move.l a0,0(a6,d0.l) ; hash[hash_val] = src
-
- move.l d5,0(a6,d6.w) ; hh[src&$FFF] = [old]hash[hash_val] {== wrk}
-
- dbra d3,incsrc
-
- cmp.l d1,a0 ; Has src reached src_end?
- bcs insctl ; Insert the X-Flag[=1] into control
-
- ;;;The main loop ends here.
- ;;;---------------------------------------------------------------------------
- ;FINALIZATION
- ;============
-
- add.l d0,d0 ; Just set the Carry [d0 is junked]
- ; Fill the rest of the control. Since the carry is set the 1st control
- ; inserted will be a copy item and the rest literals.
- FillControl:
- addx.w d7,d7
- bcc.s FillControl
-
- move.w d7,(a3) ;Write it to its output position
-
- subq.l #2,a4 ; reserve space for next controlword
- end_control_done:
- addq.l #2,a4 ; Junk new controlword
- movem.l (sp)+,d6/d7 ; Pop dst and dst_end
-
- ;Copy the literals after the word stream pointed to by a1.
- move.l a4,d0 ;d0:=Number of Bytes to increase a1
- sub.l a1,d0 ;till a1 and a4 are equally aligned.
- bcc.s did_compress
-
- ;byte- and wordstream together do exceede the size of the output buffer.
- moveq #0,d0 ; return 0 to indicate overrun
- bra.s finish2
-
- did_compress:
- moveq #3,d1
- and.w d0,d1
-
- moveq.l #0,d0 ;pad a1 up to make a1 and a4 equally aligned.
- bra.s EFLoop2
- FLoop2: move.b d0,(a1)+
- EFLoop2: dbra d1,FLoop2
-
- sub.l a4,d7 ;d7:=size of wordstream
-
- lsr.l #2,d7
- bcc.s NoWord2
- move.w (a4)+,(a1)+
- NoWord2: lsr.l #1,d7
- bcc.s NoLong2
- move.l (a4)+,(a1)+
- NoLong2 lsr.l #1,d7
- bcc.s NoQuad2
- move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- NoQuad2 lsr.l #1,d7
- bcc.s ECLoop2
- bra.s MCLoop2
-
- CLoopH2 swap d7
- CLoop2: move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- MCLoop2 move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- move.l (a4)+,(a1)+
- ECLoop2 dbra d7,CLoop2
- swap d7
- dbra d7,CLoopH2
-
- move.l a1,d0
- sub.l d6,d0 ;d0:=Final output length
- finish2: movem.l (sp)+,a3-a6/d1-d7
- rts
-